「大量のIPアドレスから大まかな地域を調べる方法って無いですかね?」
🐼「ちょっと調べてみます^^」
🐼(とは言ったものの…)
分報窓での情報提供、ありがとうございます m(_ _)m
GeoLite2を試してみよう٩( 'ω' )و
GeoLite2 データベースは、無償の IP 地理位置情報データベースで、MaxMind の GeoIP2 データベースと同等ではありますが、精度の点で多少劣ります。GeoLite2 データベースは、毎月の第一火曜日にアップデートされます。
ライセンスは「クリエイティブ・コモンズ 表示-継承 3.0 非移植ライセンス」
http://dev.maxmind.com/ja/geolite2/
GeoLite2のデータをそのまま使うこともできる。
でもまあ簡単にサクッと使いたいだけなので、日本のデータだけでいいし正規化も不要。
head -1 ./GeoLite2-City-Locations-ja.csv > loc_db_only_jp.csv
grep "日本" ./GeoLite2-City-Locations-ja.csv >> loc_db_only_jp.csv
q -H -d',' "select ip_rule.network,\
loc_jp.subdivision_1_name || loc_jp.city_name \
from ./GeoLite2-City-Blocks-IPv4.csv ip_rule \
inner join ./loc_db_only_jp.csv loc_jp \
on ip_rule.geoname_id = loc_jp.geoname_id" > ip_rule_jp.csv
require 'csv'
require 'ipaddr'
require 'pathname'
ip_file = Pathname.new(ARGV[0])
rule = CSV.read('ip_rule_jp.csv')
mapping = rule.map { |(ip_rule, loc)| [IPAddr.new(ip_rule), loc] }
filename = "#{ip_file.dirname}/#{ip_file.basename('.*')}_with_location#{ip_file.extname}"
CSV.open(filename, "wb") do |csv|
CSV.foreach(ip_file) do |(ip)|
csv << [ip, mapping.find { |(ip_rule, loc)| ip_rule.include?(ip) }&.last]
end
end
めっちゃ遅い
IPアドレス100件の処理に20秒くらい。 ブラウザ自動操作よりは速いかもだけど。 数万件(数千秒)とか待ちきれない。
※ 実行はMBP
ベンチマークして確認。
CSV.foreach(ip_file) do |(ip)|
mapping.find { |(ip_rule, loc)| ip_rule.include?(ip) }&.last
end
mappingが約6万件。
日本のデータだけにしたけどまだ全部判定させてたら遅い。
123.123.123.0/24 とかの範囲を全部個別IPに展開してBigQueryに入れ(ry
IPアドレスの最初の8bitはマスクしても変わらない。
IPが 123.x.y.z なら 123.a.b.c/s のものだけ見ればOK。
数万件の判定 → 平均400、最大5,000件の判定
def first_byte(ip)
ip.to_s.split('.', 2).first
end
mapping = mapping.group_by { |(ip_rule, loc)| first_byte(ip_rule.to_s) }
...
CSV.foreach(ip_file) do |(ip)|
csv << [ip, mapping[first_byte(ip)].find { |(ip_rule, loc)| ip_rule.include?(ip) }&.last]
end
...
判定部分: 20秒 → 0.3秒
前処理含めても以前の1/10以下の時間で完了。 (mappingのcsv読み込みに1秒くらいかかる。)
等ありましたら教えていただけるとありがたいです
m(_ _)m